package capstone.tagit;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Scanner;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.OverlayItem;

/**
 * 
 * A tag object.
 * Includes a type, date, location, description, and a configurable collection
 * 		of attributes.  Type and description are included as defaults because of OverlayItem's
 * 		built-in title and snippet fields.
 * Tag equality is currently defined by identical date and location.
 * 		This should perhaps be changed to a more easily modular option.
 * GetInfoString and ParseStringToTag are paired methods.  A change to one must
 * 		likely entail a change to the other to make sure they match.
 *
 */
public class Tag extends OverlayItem {
	/**
	 * The TagType specifying a string typeName and a Drawable marker.
	 */
	TagType type;
	/**
	 * The date at which the tag was created.
	 */
	Date date;
	/**
	 * A list of configurable attributes.  Currently can only be string attributes.
	 */
	ArrayList<Attribute<String>> attributes;
	
	/**
	 * The character used to delimit sections of the tag.
	 * Note that this would create issues if the user types this character into a text field in a tag.
	 * Documentation includes some guidelines as to how to fix this issue.
	 */
	public static String delimiter = Character.toString('|');

	/**
	 * The public constructor for a Tag object.  Must be given a location, title, and description.
	 * Instantiates an empty 
	 * @param point
	 * @param title
	 * @param snippet
	 */
	public Tag(GeoPoint point, String title, String snippet) {
		super(point, title, snippet);
		attributes = new ArrayList<Attribute<String>>();
	}
	
	public void setType(TagType type){
		this.type = type;
	}
	public void setDate(Date date){
		this.date=date;
	}
	public Date getDate(){
		return date;
	}
	public TagType getType(){return type;}
	
	/**
	 * Adds an attribute to the tag.  Adds both the attribute type
	 * into the list and a value for that attribute.
	 * @param name	The name of the attribute type
	 * @param value	The value for the attribute
	 */
	public void addAttribute(String name, String value){
		attributes.add(new Attribute<String>(name,value));
	}
	
	/**
	 * Converts the tag into a string equivalent.  Outputs it in the format
	 * <Type>|<Title>|<Description>|<Latitude>|<Longitude>|<Date>|(Optional)<Attr1>|<Attr2>....
	 * This function is paired with the parseStringtoTag function.  A change to one will entail a change
	 * to the other.
	 * @param format The specification for the date format.
	 * @return	The Tag's String equivalent.
	 */
	public String getInfoString(SimpleDateFormat format){
		String rVal = type.getName() + delimiter + getTitle() + delimiter + getSnippet() + delimiter;
		rVal = rVal.concat(Integer.toString(mPoint.getLatitudeE6()) + delimiter +
							Integer.toString(mPoint.getLongitudeE6()) + delimiter +
							format.format(date));
		for (Attribute<String> attribute: attributes){
			rVal = rVal.concat(delimiter + attribute.getValue());
		}		
//		rVal = rVal.concat(delimiter);
		
		return rVal;
	}
	
	public boolean equals(Tag t){
		return (this.date.equals(t.date)&& this.mPoint.equals(t.mPoint));
	}
	
	/**
	 * Converts a string into a tag.  Expects the format
	 * Type|Title|Description|Latitude|Longitude|Date|(Optional)Attr1|Attr2....
	 * This function is paired with the getInfoString function.  A change to one will entail a change
	 * to the other.
	 * @param toParse		The String to be parsed into a Tag
	 * @param types			A Collection of potential TagTypes available.  Will be searched through from the Type specified in the string
	 * @param attributes	A Collection of Attributes which will be filled by the function.  Each will be added into the attributes list in the Tag
	 * @param dateFormat	The specification for the date format.
	 * @return
	 */
	public static Tag parseStringToTag(String toParse, Collection<TagType> types, Collection<String> attributes, SimpleDateFormat dateFormat){
		Tag toReturn = null;
		Scanner sparse = new Scanner(toParse);
		sparse.useDelimiter("\\" + delimiter);
		while(sparse.hasNext()){
			String unparsedType = sparse.next();
			String title = sparse.next();
			String description = sparse.next();
			int latitude = sparse.nextInt();
			int longitude = sparse.nextInt();
			String unparsedDate = sparse.next();
			Date date = new Date();//default 
			try { 
				date = dateFormat.parse(unparsedDate);
			} catch (ParseException e) {
				e.printStackTrace();
			}
			GeoPoint location = new GeoPoint(latitude,longitude);
			TagType type = TagType.findTypeByName(unparsedType,types);
			toReturn = new Tag(location,title,description);
			toReturn.setMarker(type.getMarker());
			toReturn.setType(type);
			toReturn.setDate(date);
			for (String attribute : attributes){
				String value = sparse.next();
				toReturn.addAttribute(attribute,value);
			}
		}
		return toReturn;
	}
}